package com.et.protocol.core;

import android.annotation.SuppressLint;

import androidx.annotation.NonNull;

import com.et.logger.ELog;
import com.et.logger.TAGS;
import com.et.protocol.ano.Act2Code;
import com.et.protocol.ano.Act3Code;
import com.et.protocol.ano.ActCode;
import com.et.protocol.ano.Guide2Code;
import com.et.protocol.ano.GuideCode;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Queue;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;


/**
 * @author alan
 */
final class Swift implements IGuide {

    private static final byte H0 = 0x00;
    private static final byte H1 = 0x71; // 43  传递售货机标识信息
    private static final byte H2 = 0x72; // 72  售货机料道状态信息
    private static final byte H3 = 0x73; // 92  售货机外设及系统状态
    private static final byte H4 = 0x74; // 17  取货码
    private static final byte H5 = 0x75; // 151 传递料道销售统计
    private static final byte H6 = 0x76; // 16  POLL轮询
    private static final byte H8 = 0x78; // 25  签到
    private static final byte H9 = 0x79; // 60  料道运行信息
    private static final byte Ha = 0x7A; // 22  系统配置信息
    private static final byte Hb = 0x7B; // 81  商品销售汇总
    private static final byte HC = 0x7C; // 34  出货
    private static final byte Hd = 0x7D; // 15  机器运行信息
    private static final byte He = 0x7E; // 54  料道商品信息
    private static final byte Hf = 0x7F; // 102 料道价格信息


    private static final byte[] SACK_1 = {H1, H0, H1};
    private static final byte[] SACK_2 = {H2, H0, H2};
    private static final byte[] SACK_3 = {H3, H0, H3};
    private static final byte[] SACK_4 = {H4, H0, H4};
    private static final byte[] SACK_5 = {H5, H0, H5};
    private static final byte[] SACK_6 = {H6, H0, H6};
    private static final byte[] SACK_8 = {H8, H0, H8};
    private static final byte[] SACK_9 = {H9, H0, H9};
    private static final byte[] SACK_a = {Ha, H0, Ha};
    private static final byte[] SACK_b = {Hb, H0, Hb};
    private static final byte[] SACK_c = {HC, H0, HC};
    private static final byte[] SACK_d = {Hd, H0, Hd};
    private static final byte[] SACK_e = {He, H0, He};
    private static final byte[] SACK_f = {Hf, H0, Hf};

    // 带协议的长度
    private static final int LEN_1 = 43;
    private static final int LEN_2 = 72;
    private static final int LEN_3 = 92;
    private static final int LEN_4 = 17;
    private static final int LEN_5 = 151;
    private static final int LEN_6 = 16;
    private static final int LEN_8 = 25;
    private static final int LEN_9 = 60;
    private static final int LEN_a = 22;
    private static final int LEN_b = 81;
    private static final int LEN_c = 34;
    private static final int LEN_d = 15;
    private static final int LEN_e = 54;
    private static final int LEN_f = 102;

    // 不带协议的， -5 78 ef ee fe + sum
    private static final int DLN_1 = 38;
    private static final int DLN_2 = 67;
    private static final int DLN_3 = 87;
    private static final int DLN_4 = 12;
    private static final int DLN_5 = 146;
    private static final int DLN_6 = 11;
    private static final int DLN_8 = 20;
    private static final int DLN_9 = 55;
    private static final int DLN_a = 17;
    private static final int DLN_b = 76;
    private static final int DLN_c = 29;
    private static final int DLN_d = 10;
    private static final int DLN_e = 49;
    private static final int DLN_f = 97;

    private static final byte b_ef = -17;
    private static final byte b_ee = -18;
    private static final byte b_fe = -2;
    private static final byte b_00 = 0x00;
    private static final byte b_76 = 0x76;
    private static final byte b_15 = 0x15;
    private static final byte b_8b = (byte) 0x8B;
    private static final byte p_a = 0x00;
    private static final byte p_b = 0x00;
    private static final byte p_acc = 0x0c; // 760076

    private SerialNative serial;
    private final OutputStream outputStream;
    private final InputStream inputStream;

    /*存储实时指令*/
    private byte[] tmp1;
    private byte[] tmp3;
    private byte[] tmp4;
    private byte[] tmp5;
    private byte[] tmp6;
    private byte[] tmp8; // 签到信息
    private byte[] tmpB; // 销售汇总
    private byte[] tmpC; // 出货信息
    private byte[] tmpD; // 运行状态
    private byte[][] tmp2; // 料道运行补充 2s/次
    private byte[][] tmp9; // 料道运行信息 2s/次
    private byte[][] tmpA; // 货柜配置信息 2s/次
    private byte[][] tmpE; // 料道商品序号
    private byte[][] tmpF; // 料道商品价格

    /*串口指令组合状态*/
    private int step = S_idle;
    private static final int S_idle = 0x00;
    private static final int S_head = 0x10;
    private static final int S_head_ef = 0x11;
    private static final int S_head_ef_ee = 0x12;
    private static final int S_head_ef_ee_fe = 0x13;
    private static final int S_76 = 0x14;
    private static final int S_7600 = 0x15;
    private static final int S_7615 = 0x17;

    /*通信缓存*/
    private int len;
    private static final int CAP = 512;     // 初始区大小
    private static final int LIMIT = 384;   // 溢出告警线
    private static final int RW_LEN = 128;  // 读 &写缓存大小
    private final byte[] reader = new byte[CAP];  // 数据读取缓存区域
    private int off = 0; // 有效数据开头(包含)
    private int end = 0; // 有效数据结尾(排除)
    private int bug = 0; // 按字节爬虫有效数据
    private byte[] majorGuide = null; // 出货指令缓存
    private boolean noAck73 = true;   // 不回复73指令
    /*外部数据观察者*/
    private final IObserver observer;
    private int state = IDLE;
    private static final int IDLE = 0;
    private static final int DIS = 1;
    private static final int CON = 2;
    private final Queue<byte[]> guideQueue = new LinkedBlockingQueue<>();
    private final Timer timer;
    private boolean request = true; // 需要请求权限
    private final Executor userThread = Executors.newCachedThreadPool();
    private Thread fixThread;

    static Swift newInstance(@NonNull String portName, int baud, IObserver observer) throws IOException {
        return new Swift(portName, baud, observer);
    }

    private Swift(String portName, int baudRate, IObserver observer) throws IOException {
        this.observer = observer;
        serial = new SerialNative(new File(portName), baudRate, 0);
        outputStream = serial.getOutputStream();
        inputStream = serial.getInputStream();

        fixThread = new Thread(() -> {
            ELog.Companion.d(TAGS.protocol, "FixThread Start");
            while (!Thread.interrupted()) {
                try {
                    cacheMonitor();
                    if (inputStream != null) end += inputStream.read(reader, end, RW_LEN);
                    this.dealNewData(); // 处理读取到的数据
                    if (state == DIS) {
                        if (observer != null) {
                            userThread.execute(() -> observer.action1(ActCode.ACT_CONNECT));
                        }
                    }
                    state = CON;
                } catch (IOException ignored) {
                    ELog.Companion.d(TAGS.protocol, "串口IO异常");
                    step = S_idle;
                    off = end = bug = 0;
                }
            }
        });

        fixThread.start();

        timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (state == IDLE) {
                    if (observer != null) {
                        state = DIS;
                        userThread.execute(() -> observer.action1(ActCode.ACT_CONNECT));
                    }
                }
                if (state == CON) state = IDLE;
            }
        }, 20_000L, 15_000L);
    }

    /*缓存监控*/
    private void cacheMonitor() {
        if (end == off) {
            off = bug = 0; // 直接回归
        } else if (end > LIMIT) { // 缓存区域溢出告警
            if (end - off > 0) {
                System.arraycopy(reader, off, reader, 0, end - off);
            }
            end = end - off;
            off = bug = 0; // 回归
        }
    }

    /*新读取数据的处理*/
    private void dealNewData() throws IOException {
        while (bug < end) {
            // 读取数据缓存字节
            switch (step) {
                case S_idle: // 重置状态
                    checkHeadAndSetLen();
                    break;
                case S_head: // 匹配到开头
                    if (reader[bug] == b_ef) {
                        ++bug;
                        step = S_head_ef;
                        break;
                    }
                    step = S_idle;
                    break;
                case S_head_ef:
                    if (reader[bug] == b_ee) {
                        ++bug;
                        step = S_head_ef_ee;
                        break;
                    }
                    step = S_idle;
                    break;
                case S_head_ef_ee:
                    if (reader[bug] == b_fe) {
                        ++bug;
                        step = S_head_ef_ee_fe;
                        break;
                    }
                    step = S_idle;
                    break;
                case S_head_ef_ee_fe:
                    detectionLen(); // 侦察长度
                    break;
                // ACK 判断
                case S_76:
                    switch (reader[bug]) {
                        case b_ef:
                            ++bug;
                            step = S_head_ef; // 76 EF
                            break;
                        case b_00:
                            ++bug;
                            step = S_7600; // 76 00
                            break;
                        case b_15:
                            ++bug;
                            step = S_7615; // 76 15
                            break;
                        default:
                            step = S_idle;
                    }
                    break;
                // ACK 76 00
                case S_7600:
                    if (reader[bug] == b_76) {
                        ++bug;
                        if (majorGuide != null) {
                            majorGuide[0] = p_acc;
                            ELog.Companion.d(TAGS.protocol, "760076 -> " + ByteUtil.toHex(majorGuide, 0, majorGuide.length));
                            final byte[] bytes = new byte[majorGuide.length];
                            System.arraycopy(majorGuide, 1, bytes, 0, bytes.length - 2);
                            if (observer != null) {
                                userThread.execute(() -> observer.action2(Act2Code.ACT_ACCEPT, bytes));
                            }
                        } else {
                            ELog.Companion.d(TAGS.protocol, "760076");
                        }
                    }
                    step = S_idle;
                    break;
                // ACK 76 15
                case S_7615:
                    if (reader[bug] == b_8b) {
                        ++bug;
                        if (majorGuide != null) {
                            ELog.Companion.d(TAGS.protocol, "拒绝出货:" + ByteUtil.toHex(majorGuide, 0, majorGuide.length));
                            final byte[] bytes = new byte[majorGuide.length];
                            System.arraycopy(majorGuide, 1, bytes, 0, majorGuide.length - 2);
                            majorGuide = null;
                            if (observer != null) {
                                userThread.execute(() -> observer.action2(Act2Code.ACT_REFUSE, bytes));
                            }
                        } else {
                            ELog.Companion.d(TAGS.protocol, "76158b");
                        }
                    }
                    step = S_idle;
                    break;
            }
        }
    }

    /*开头匹配正确,侦察指令长度*/
    private void detectionLen() throws IOException {
        if (len > end - off) {
            bug = end; // 指令长度不够,爬虫到末端等待新数据到来
            return;
        }
        step = S_idle; // 长度足够,状态重置
        if (!ByteUtil.isOk(reader, off, len)) {
            ELog.Companion.d(TAGS.protocol, "Protocol not pass:" + ByteUtil.toHex(reader, off, end));
            off += len;
            if (end == off) {
                end = off = 0; // 回归,回归到缓冲起始
            }
            bug = off;
            return;
        }

        boolean bool = false;
        int box;
        switch (reader[off]) {
            case 0x71:
                ack(SACK_1);
                if (tmp1 == null) {
                    tmp1 = new byte[DLN_1];
                    bool = true;
                }
                for (int i = 0; i < DLN_1; i++) {
                    if (tmp1[i] != reader[off + i + 4]) {
                        tmp1[i] = reader[off + i + 4];
                        bool = true;
                    }
                }

                if (request && tmp8 != null) {
                    request = false;
                }
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "1:" + ByteUtil.toLog(tmp1));
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_01, tmp1));
                    }
                }
                break;
            case 0x72:
                ack(SACK_2);
                box = reader[off + 4];
                if (box > 0 && box < 12) {
                    if (tmp2 == null) tmp2 = new byte[12][];
                    if (tmp2[box] == null) {
                        tmp2[box] = new byte[DLN_2];
                        bool = true;
                    }
                    for (int i = 0; i < DLN_2; i++) {
                        if (tmp2[box][i] != reader[off + i + 4]) {
                            tmp2[box][i] = reader[off + i + 4];
                            bool = true;
                        }
                    }

                    if (bool && observer != null) {
                        ELog.Companion.d(TAGS.protocol, "2:" + ByteUtil.toLog(tmp2[box]));
                        userThread.execute(() -> observer.action3(Act3Code.ACT_02, tmp2[box]));
                    }
                }
                break;
            case 0x73:
                if (noAck73) break;
                ack(SACK_3);
                if (tmp3 == null) {
                    tmp3 = new byte[DLN_3];
                    bool = true;
                }
                for (int i = 0; i < DLN_3; i++) {
                    if (tmp3[i] != reader[off + i + 4]) {
                        tmp3[i] = reader[off + i + 4];
                        bool = true;
                    }
                }
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "3:" + ByteUtil.toLog(tmp3));
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_03, tmp3));
                    }
                }
                break;
            case 0x74:
                ack(SACK_4);
                if (tmp4 == null) {
                    tmp4 = new byte[DLN_4];
                    bool = true;
                }
                for (int i = 0; i < DLN_4; i++) {
                    if (tmp4[i] != reader[off + i + 4]) {
                        tmp4[i] = reader[off + i + 4];
                        bool = true;
                    }
                }
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "4:" + ByteUtil.toLog(tmp4));
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_04, tmp4));
                    }
                }
                break;
            case 0x75:
                ack(SACK_5);
                if (tmp5 == null) {
                    tmp5 = new byte[DLN_5];
                    bool = true;
                }
                for (int i = 0; i < DLN_5; i++) {
                    if (tmp5[i] != reader[off + i + 4]) {
                        tmp5[i] = reader[off + i + 4];
                        bool = true;
                    }
                }
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "5:" + ByteUtil.toLog(tmp5));
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_05, tmp5));
                    }
                }
                break;
            case 0x76:
                if (tmp6 == null) {
                    tmp6 = new byte[DLN_6];
                    bool = true; // 初次要回调
                }
                for (int i = 0; i < DLN_6; i++) {
                    if (tmp6[i] != reader[off + i + 4]) {
                        tmp6[i] = reader[off + i + 4];
                        bool = true;
                    }
                }

                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "6 R:" + ByteUtil.toLog(tmp6));
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_06, tmp6));
                    }
                }

                // 重新签到
                if (tmp8 == null) {
                    ELog.Companion.d(TAGS.protocol, "swift reboot");
                    byte[] reboot = new byte[]{0x00, 0x07, 0x03, 0x00, 0x00};
                    this.poll(reboot);
                    break;
                }

                // 针对出货 760x 7603
                if (majorGuide != null && majorGuide[0] != p_acc) {
                    poll(majorGuide);
                    break;
                }

                // 普通
                if (!guideQueue.isEmpty()) {
                    // 普通指令缓存
                    byte[] general = guideQueue.poll();
                    if (general != null) {
                        ELog.Companion.d(TAGS.protocol, "76 W:" + ByteUtil.toLog(general));
                        poll(general);
                        break;
                    }
                }
                ack(SACK_6);
                break;
            case 0x78:
                request = true;
                noAck73 = reader[4 + off] < 0x02 && reader[5 + off] < 0x16;
                if (reader[4 + off] > 0x0f) {
                    byte[] t78 = new byte[3];
                    t78[0] = (byte) 0x78;
                    char[] key = {0x3C, 0x7B, 0x4D, 0xF9, 0xCF, 0x09, 0x13, 0xA5, 0xEE, 0xFF, 0x45, 0x7A, 0x96, 0xE4, 0xE6, 0xB3};
                    byte[] md5 = Md5Util.getInstance().md5(new char[]{(char) ByteUtil.sum(reader, off + 4, 13)}, key);
                    for (byte t : md5) {
                        t78[1] += t;
                    }
                    t78[2] = (byte) (t78[0] + t78[1]);
                    ack(t78);
                } else {
                    ack(SACK_8);
                }
                if (tmp8 == null) {
                    tmp8 = new byte[DLN_8];
                    bool = true;
                }
                for (int i = 0; i < DLN_8; i++) {
                    if (i > 5 && i < 13) continue;
                    if (tmp8[i] != reader[off + i + 4]) {
                        bool = true;
                        tmp8[i] = reader[off + i + 4];
                    }
                }
                ELog.Companion.d(TAGS.protocol, "8:" + ByteUtil.toLog(tmp8));
                if (bool) {
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_08, tmp8));
                    }
                }
                break;
            case 0x79:
                ack(SACK_9);
                box = reader[off + 4];
                if (box > 0 && box < 12) {
                    if (tmp9 == null) tmp9 = new byte[12][];
                    if (tmp9[box] == null) {
                        tmp9[box] = new byte[DLN_9];
                        bool = true;
                    }
                    for (int i = 0; i < DLN_9; i++) {
                        if (tmp9[box][i] != reader[off + i + 4]) {
                            tmp9[box][i] = reader[off + i + 4];
                            bool = true;
                        }
                    }

                    if (bool && observer != null) {
                        ELog.Companion.d(TAGS.protocol, "9:" + ByteUtil.toLog(tmp9[box]));
                        userThread.execute(() -> observer.action3(Act3Code.ACT_09, tmp9[box]));
                    }
                }
                break;
            case 0x7a:
                ack(SACK_a);
                box = reader[off + 4];
                if (box < 0 || box > 11) break;
                if (tmpA == null) tmpA = new byte[12][];
                if (tmpA[box] == null) {
                    tmpA[box] = new byte[DLN_a];
                    bool = true;
                }
                for (int i = 0; i < DLN_a; i++) {
                    if (tmpA[box][i] != reader[off + i + 4]) {
                        tmpA[box][i] = reader[off + i + 4];
                        bool = true;
                    }
                }

                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "a:" + ByteUtil.toLog(tmpA[box]));
                    if (observer != null) {
                        userThread.execute(() -> observer.action3(Act3Code.ACT_0a, tmpA[box]));
                    }
                }
                break;
            case 0x7b:
                ack(SACK_b);
                if (tmpB == null) {
                    tmpB = new byte[DLN_b];
                    bool = true;
                }
                for (int i = 0; i < DLN_b; i++) {
                    if (tmpB[i] != reader[off + i + 4]) {
                        tmpB[i] = reader[off + i + 4];
                        bool = true;
                    }
                }
                ELog.Companion.d(TAGS.protocol, "b:" + ByteUtil.toLog(tmpB));
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_0b, tmpB));
                    }
                }
                break;
            case 0x7c:
                majorGuide = null;
                ack(SACK_c);
                bool = false;
                if (tmpC == null) {
                    tmpC = new byte[DLN_c];
                    bool = true;
                }
                for (int i = 0; i < DLN_c; i++) {
                    if (reader[i + off + 4] != tmpC[i]) {
                        bool = true;
                        tmpC[i] = reader[i + off + 4];
                    }
                }
                ELog.Companion.d(TAGS.protocol, "c:" + ByteUtil.toLog(tmpC));
                if (bool) {
                    final byte[] t7c = new byte[DLN_c];
                    System.arraycopy(tmpC, 0, t7c, 0, DLN_c);
                    if (observer != null)
                        userThread.execute(() -> observer.action2(Act2Code.ACT_0c, t7c));
                }
                break;
            case 0x7d:
                ack(SACK_d);
                if (tmpD == null) {
                    tmpD = new byte[DLN_d];
                    bool = true;
                }
                for (int i = 0; i < DLN_d; i++) {
                    if (tmpD[i] != reader[off + i + 4]) {
                        tmpD[i] = reader[off + i + 4];
                        bool = true;
                    }
                }


                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    ELog.Companion.d(TAGS.protocol, "d:" + ByteUtil.toLog(tmpD));
                    if (observer != null) {
                        userThread.execute(() -> observer.action2(Act2Code.ACT_0d, tmpD));
                    }
                }
                break;
            case 0x7e:
                ack(SACK_e);
                box = reader[off + 4];
                if (box < 0 || box > 11) break;
                if (tmpE == null) tmpE = new byte[12][];
                if (tmpE[box] == null) {
                    tmpE[box] = new byte[DLN_e];
                    bool = true;
                }
                for (int i = 0; i < DLN_e; i++) {
                    if (tmpE[box][i] != reader[off + i + 4]) {
                        tmpE[box][i] = reader[off + i + 4];
                        bool = true;
                    }
                }
                ELog.Companion.d(TAGS.protocol, "e:" + ByteUtil.toLog(tmpE[box]));
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    if (observer != null) {
                        userThread.execute(() -> observer.action3(Act3Code.ACT_0e, tmpE[box]));
                    }
                }
                break;
            case 0x7f:
                ack(SACK_f);
                box = reader[off + 4];
                if (box < 0 || box > 11) break;
                if (tmpF == null) tmpF = new byte[12][];
                if (tmpF[box] == null) {
                    tmpF[box] = new byte[DLN_f];
                    bool = true;
                }
                for (int i = 0; i < DLN_f; i++) {
                    if (tmpF[box][i] != reader[off + i + 4]) {
                        tmpF[box][i] = reader[off + i + 4];
                        bool = true;
                    }
                }
                ELog.Companion.d(TAGS.protocol, "f:" + ByteUtil.toLog(tmpF[box]));
                if (bool) { // 变化发送,用户自己保存,超时不处理则被重写
                    if (observer != null) {
                        userThread.execute(() -> observer.action3(Act3Code.ACT_0f, tmpF[box]));
                    }
                }
                break;
        }

        off += len;
        if (end == off) {
            end = off = 0; // 回归
        }
        bug = off;
    }

    /*76 poll*/
    private void poll(@NonNull byte[] data) throws IOException {
        if (outputStream != null) {
            data[0] = 0x76;
            data[data.length - 1] = ByteUtil.sum(data, 0, data.length - 1);
            outputStream.write(data);
            outputStream.flush();
            data[0] = p_a; // 销毁协议头
            data[data.length - 1] = p_b; // 销毁校验和
            ELog.Companion.d(TAGS.protocol, "76↓:" + ByteUtil.toLog(data));
        }
    }

    private void ack(byte[] data) throws IOException {
        if (outputStream != null) {
            outputStream.write(data);
            outputStream.flush();
        }
    }

    /*检查开头字节,更新缓存长度值*/
    private void checkHeadAndSetLen() {
        step = S_head; // 默认匹配到
        off = bug;     // 更新数据开头
        switch (reader[bug]) { // 当前爬虫所待的位置
            case H1:
                len = LEN_1;
                break;
            case H2:
                len = LEN_2;
                break;
            case H3:
                len = LEN_3;
                break;
            case H4:
                len = LEN_4;
                break;
            case H5:
                len = LEN_5;
                break;
            case H6:
                len = LEN_6;
                step = S_76; // 76 状态
                break;
            case H8:
                len = LEN_8;
                break;
            case H9:
                len = LEN_9;
                break;
            case Ha:
                len = LEN_a;
                break;
            case Hb:
                len = LEN_b;
                break;
            case HC:
                len = LEN_c;
                break;
            case Hd:
                len = LEN_d;
                break;
            case He:
                len = LEN_e;
                break;
            case Hf:
                len = LEN_f;
                break;
            default:
                step = S_idle; // 状态重置
        }
        ++bug; // 爬虫前进
    }

    @SuppressLint("SwitchIntDef")
    @Override
    public boolean guide(int code) {
        switch (code) {
            case GuideCode.GUI_53:
                if (majorGuide != null) {
                    if (majorGuide[0] == p_a && majorGuide[majorGuide.length - 1] == p_b)
                        return false;
                    majorGuide = null;
                    return true;
                }
                return false;
            case GuideCode.GUI_88:
                try {
                    ELog.Companion.d(TAGS.protocol, "swift release and clear cache");
                    if (fixThread != null) {
                        fixThread.interrupt();
                        fixThread = null;
                    }
                    if (timer != null) timer.cancel();
                    if (serial != null) {
                        serial.close();
                        serial = null;
                    }
                    tmp1 = tmp3 = tmp4 = tmp5 = tmp6 = tmp8 = tmpC = tmpD = tmpB = null;
                    tmp2 = tmp9 = tmpA = tmpE = tmpF = null;
                    len = off = end = bug = 0;
                    if (observer != null) {
                        state = DIS;
                        userThread.execute(() -> observer.action1(ActCode.ACT_CONNECT));
                    }
                    return true;
                } catch (Exception e) {
                    ELog.Companion.d(TAGS.protocol, "Exit Exception");
                }
                return false;
        }
        return false;
    }

    /*下发指令*/
    @Override
    public boolean guide2(int code, byte[] data) {
        /* 下发出货 */
        data[0] = 0x76;
        data[1] = (byte) code;
        if (code == Guide2Code.GUI_03) {
//            if (data[2] > 9 || data[2] < 8) return false;
            if (majorGuide == null) {
                majorGuide = data;
                return true;
            }
            return false;
        }
        /* 普通指令 */
        if (guideQueue.size() > 1000) guideQueue.clear();
        guideQueue.offer(data);
        return true;
    }

    public int query(int code) {
        return state;
    }

    @SuppressLint("SwitchIntDef")
    public byte[] query2(@Act2Code int code) {
        switch (code) {
            case Act2Code.ACT_01:
                return tmp1;
            case Act2Code.ACT_03:
                return tmp3;
            case Act2Code.ACT_04:
                return tmp4;
            case Act2Code.ACT_05:
                return tmp5;
            case Act2Code.ACT_06:
                return tmp6;
            case Act2Code.ACT_08:
                return tmp8;
            case Act2Code.ACT_0b:
                return tmpB;
            case Act2Code.ACT_0c:
                return tmpC;
            case Act2Code.ACT_0d:
                return tmpD;
        }
        return null;
    }

    @SuppressLint("SwitchIntDef")
    public byte[] query3(int code, int box) {
        switch (code) {
            case Act3Code.ACT_02:
                if (tmp2 == null) return null;
                if (box < 1 || box > 11) return null;
                return tmp2[box];
            case Act3Code.ACT_09:
                if (tmp9 == null) return null;
                if (box < 1 || box > 11) return null;
                return tmp9[box];
            case Act3Code.ACT_0a:
                if (tmpA == null) return null;
                if (box < 1 || box > 11) return null;
                return tmpA[box];
            case Act3Code.ACT_0e:
                if (tmpE == null) return null;
                if (box < 1 || box > 11) return null;
                return tmpE[box];
            case Act3Code.ACT_0f:
                if (tmpF == null) return null;
                if (box < 1 || box > 11) return null;
                return tmpF[box];
        }
        return null;
    }
}
